//
// Copyright (c)1998-2011 Pearson Education, Inc. or its affiliate(s).
// All rights reserved.
//
package openadk.library.impl;
import openadk.library.*;
import openadk.library.common.*;
import openadk.library.infra.*;
import openadk.library.threadpool.ThreadPoolManager;
import org.eclipse.jetty.http.*;
import org.eclipse.jetty.http.ssl.SslContextFactory;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.NCSARequestLog;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.bio.SocketConnector;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.RequestLogHandler;
import org.eclipse.jetty.server.ssl.SslSocketConnector;
import org.eclipse.jetty.util.*;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ThreadPool;
import org.eclipse.jetty.util.MultiException;
import org.apache.log4j.Category;
import org.apache.log4j.Logger;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import javax.net.ssl.SSLServerSocket;
/**
* Transport class for the HTTP and HTTPS protocols.
* <p>
*
* One instance of HttpTransport is shared among all zones that use the HTTP or
* HTTPS protocols. When activated, it creates an internal Jetty HTTP/HTTPS web
* server for use by all zones the agent is connected to using these protocols.
* Each zone then instantiates its own HttpProtocolHandler, which is responsible
* for sending and receiving messages. (The HttpTransport class does not send or
* receive messages.)
* <p>
*
* Because many SIF Agents may use the ADK, no default HTTP or HTTPS port is
* assigned to push mode agents by the class framework. It is the developer's
* responsibility to assign a default port (pull-mode agents do not require a
* port be assigned.) To do so, use one of the following methods:
* <p>
*
* <ul>
* <li> Set the <code>adk.transport.http.port</code> system property prior to
* creating your agent's Zones and/or Topics. This property can be set
* programmatically by calling the System.setProperty method, or via the -D
* option on the Java command-line. </li>
* <li> Call the setPort method on the default HttpProperties and/or
* HttpsProperties objects prior to creating your agent's Zones and/or Topics.
* The following block of code demonstrates:<br/> <br/> <code>
*
* // Set transport properties for HTTP<br/>
* Agent myAgent = ...<br/>
* HttpProperties http = agent.getDefaultHttpProperties();<br/>
* http.setPort( 7081 );<br/>
* <br/>
* // Set transport properties for HTTPS<br/>
* HttpsProperties https = agent.getDefaultHttpsProperties();<br/>
* https.setPort( 7082 );<br/>
* https.setKeystorePassword( "changeit" );<br/>
* ...<br/>
* <br/>
* </li>
* </ul>
*
* @author Eric Petersen
* @version ADK 1.0
*/
public class HttpTransport extends TransportImpl {
/** DO NOT ENABLE IN PRODUCTION CODE * */
private static final boolean USE_CDATA_IN_PUSHURL = false;
/**
* The root log Category. Subcategories exist for each zone, where the
* subcategory name is "Agent.<i>zoneId</i>". The ADK uses the root
* Category when writing log events that are not associated with a specific
* zone. Your agent may also use this Category to post log events.
*/
protected Category log = null;
/**
* The internal Jetty http/https server
*/
protected static Server sServer = null;
/**
* a reference to the ThreadPoolManager instance to execute pull tasks in
*/
protected ThreadPoolManager fThreadPoolManager = null;
/**
* Constructs an HttpTransport for HTTP or HTTPS
*
* @param props
* Transport properties (usually an instance of HttpProperties or
* HttpsProperties)
*/
protected HttpTransport(HttpProperties props) throws ADKTransportException {
super(props);
log = Logger.getLogger("ADK.Agent.transport$" + fProps.getProtocol());
}
/**
* Clone this HttpTransport.
* <p>
*
* Cloning a transport results in a new HttpTransport instance with
* HttpProperties that inherit from this object's properties. However, the
* Jetty web server owned by this transport will be shared with the cloned
* instance.
*/
public Transport cloneTransport() throws ADKTransportException {
HttpProperties props = null;
if (fProps instanceof HttpProperties)
props = new HttpProperties((HttpProperties) fProps.getParent());
else if (fProps instanceof HttpsProperties)
props = new HttpsProperties((HttpsProperties) fProps.getParent());
HttpTransport t = new HttpTransport(props);
// This object and the clone share the Jetty server
t.sServer = sServer;
return t;
}
public synchronized boolean initialize(Agent agent, AgentProperties agentProps, boolean isPushModeZone)
throws ADKTransportException
{
HttpProperties props = (HttpProperties) fProps;
fThreadPoolManager = agent.getThreadPoolManager();
int poolSize = 8;
if(fThreadPoolManager != null) {
poolSize = fThreadPoolManager.getMaximumPoolSize();
}
boolean webAppEnabled = props.getServletEnabled();
// Create the http server if it doesn't exist. All HttpTransport
// objects share once instance of the server.
if ( (sServer == null || !sServer.isStarted() )
&& ( webAppEnabled || isPushModeZone ) ) {
if ((ADK.debug & ADK.DBG_TRANSPORT) != 0 && log.isInfoEnabled()) {
log.info("Activating " + fProps.getProtocol().toUpperCase()
+ " transport...");
}
if (sServer == null) {
try {
sServer = new org.eclipse.jetty.server.Server();
sServer.setThreadPool(new QueuedThreadPool(poolSize));
//HandlerCollection handlers = new HandlerCollection();
//handlers.addHandler(new ContextHandlerCollection());
sServer.setHandler(new ContextHandlerCollection());
} catch (NoClassDefFoundError ncdfe) {
String message = null;
if (ncdfe.getMessage().endsWith("LogFactory")) {
message = "Unable to start Jetty Server. Please add commons-logging.jar to the classpath."
+ ncdfe.getMessage();
} else {
message = "Unable to start Jetty Server. "
+ ncdfe.getMessage();
}
ADKTransportException adkte = new ADKTransportException(
message, null, ncdfe);
throw adkte;
}
// The following is an undocumented feature of the ADK
if (agentProps.getProperty("adk.transport.NCSARequestLog",
false)) {
// The following code turns on standard weblogging, but may
// not turn
// out to be all that useful
NCSARequestLog serverRequestLog = new NCSARequestLog();
File f = new File(agent.getHomeDir() + "/weblogs");
f.mkdirs();
serverRequestLog.setFilename(f.getAbsolutePath()
+ "/yyyy_mm_dd.request.log");
serverRequestLog.setRetainDays(30);
serverRequestLog.setAppend(true);
serverRequestLog.setExtended(true);
HandlerCollection handlers = (HandlerCollection) sServer.getHandler();
// is the following needed? shouldn't be serving files or favicon
//handlers.addHandler(new DefaultHandler());
RequestLogHandler requestLogHandler = new RequestLogHandler();
requestLogHandler.setRequestLog(serverRequestLog);
handlers.addHandler(requestLogHandler);
}
}
}
return sServer != null;
}
/**
* Activate this Transport for an agent. This method is called when the
* agent is initialized
*
* @param agent
* The zone
*/
public synchronized void activate(Agent agent) throws ADKTransportException {
if(sServer == null || !sServer.isStarted()) {
initialize(agent, agent.getProperties(), false);
}
try {
// Start the server if not already started
if (sServer != null && sServer.isStopped()) {
if ((ADK.debug & ADK.DBG_TRANSPORT) != 0 && log.isInfoEnabled()) {
log.info("Starting HTTP/HTTPS server...");
}
sServer.start();
}
} catch (Exception ex) {
ADKTransportException te = new ADKTransportException(
"Failed to activate " + fProps.getProtocol().toUpperCase()
+ " transport on " + getHost() + ":" + getPort(),
null, ex);
if (ex instanceof MultiException) {
MultiException me = (MultiException) ex;
List inners = me.getThrowables();
for (Iterator it = inners.iterator(); it.hasNext();) {
Throwable th = (Throwable) it.next();
te.add(th);
}
} else {
te.add(ex);
}
ADKUtils._throw(te, log);
}
}
/**
* Activate this Transport for a zone. This method is called for every zone
* when it is being connected
*
* @param zone
* The zone
*/
public synchronized void activate(Zone zone) throws ADKTransportException {
boolean isPushMode = zone.getProperties().getMessagingMode() == AgentMessagingMode.PUSH;
if ( initialize( zone.getAgent(), zone.getProperties(), isPushMode )) {
if(isPushMode) {
// Configure the server specifically for this Transport
configureServer( zone );
}
// activate(zone.getAgent());
}
}
/**
* Is this Transport activated?
*/
public boolean isActive(Zone zone) throws ADKTransportException {
if (zone.getProperties().getMessagingMode() == AgentMessagingMode.PUSH) {
if (sServer != null && sServer.isStarted()) {
Connector[] listeners = sServer.getConnectors();
for (int i = 0; i < listeners.length; i++) {
if (!listeners[i].isStarted())
return false;
}
} else
return false;
}
return true;
}
/**
* Shutdown this Transport
*/
public synchronized void shutdown() {
if (sServer != null) {
try {
// Remove listener
int port = getPort();
Connector[] listeners = sServer.getConnectors();
for (int i = 0; i < listeners.length; i++) {
if (listeners[i] instanceof SocketConnector
&& listeners[i].getPort() == port) {
sServer.removeConnector(listeners[i]);
break;
}
}
sServer.stop();
} catch (Exception ie) {
log.warn("Error shutting down Jetty Server: " + ie, ie);
}
}
}
/**
* Configure the Jetty server for HTTP as needed based on the settings of
* this Transport object. If the server does not have a SocketListener on
* the port specified for this transport, one is created. Jetty
* configuration is performed dynamically as HttpTransport objects are
* created, so listeners are added to the server the first time they are
* needed.
*/
protected void configureServer(Zone zone) throws ADKTransportException {
SocketConnector newListener = null;
if (fProps.getProtocol().equalsIgnoreCase("http")){
newListener = configureHttp(zone);
} else if (fProps.getProtocol().equalsIgnoreCase("https")){
newListener = configureHttps(zone);
} else {
throw new InternalError(
"HttpTransport object configured with properties for another protocol: "
+ fProps.getProtocol());
}
if( newListener != null ){
sServer.addConnector(newListener);
/* try
{
newListener.start();
newListener.open();
}
catch( Exception le ){
ADKUtils._throw( new ADKTransportException( "Error starting SocketListener: " + le.getMessage(), zone, le ), log );
}
*/
if( fProps.getProtocol().equalsIgnoreCase("https") ){
String allowedCiphers = fProps.getProperty( "ciphers" );
if( allowedCiphers != null && allowedCiphers.length() > 0 ){
log.debug( "Setting the set of allowed ciphers to " + allowedCiphers );
String[] allowed = allowedCiphers.split( "," );
SslSocketConnector jsse = (SslSocketConnector)newListener;
List<String> ciphers = new ArrayList<String>();
for( String cipher : jsse.getSslContextFactory().getIncludeCipherSuites()){
if( Arrays.binarySearch( allowed, cipher ) < 0 ) {
log.debug( "Disabling cipher: " + cipher );
}else {
log.debug( "Enabling cipher: " + cipher );
ciphers.add( cipher );
}
}
String[] enabled = new String[ ciphers.size() ];
ciphers.toArray( enabled );
jsse.getSslContextFactory().setIncludeCipherSuites(enabled);
// for( String pro : socket.getEnabledProtocols() ){
// System.out.println( pro );
// }
//
for( String cipher : jsse.getSslContextFactory().getIncludeCipherSuites() ){
log.debug( cipher + " is enabled for this session." );
}
}
}
}
}
/**
* Configures an HTTP listener
* @param zone The zone to use for configuring properties
* @return The SocketListener that was configured, or null
* @throws ADKTransportException
*/
protected SocketConnector configureHttp(Zone zone) throws ADKTransportException {
int port = getPort();
if (port == -1)
throw new ADKTransportException(
"The agent is not configured with a default HTTP port",
zone);
String optHost = getHost();
// If there is no SocketListener on this port, create one
Connector listener = null;
Connector[] listeners = sServer.getConnectors();
if (listeners != null) {
for (int i = 0; i < listeners.length; i++) {
if (listeners[i] instanceof SocketConnector
&& listeners[i].getPort() == port) {
if (optHost != null && listeners[i].getHost().equalsIgnoreCase(optHost))
listener = listeners[i];
}
}
}
if (listener == null) {
if ((ADK.debug & ADK.DBG_TRANSPORT) != 0 && log.isInfoEnabled()) {
if (optHost != null) {
log.info("Creating HTTP listener for push mode on "
+ optHost + ":" + port);
} else {
log.info("Creating HTTP listener for push mode on port "
+ port);
}
}
SocketConnector http = new SocketConnector();
configureSocketListener(http, port, optHost);
return http;
} else {
if ((ADK.debug & ADK.DBG_TRANSPORT) != 0 && log.isDebugEnabled()) {
if (optHost != null) {
log.debug("Already a HTTP listener on " + optHost + ":"
+ port);
} else {
log.debug("Already a HTTP listener on port " + port);
}
}
}
return null;
}
/**
* Configure the Jetty server for HTTPS as needed based on the settings of
* this Transport object. If the server does not have a JSSEListener on the
* port specified for this transport, one is created. Jetty configuration is
* performed dynamically as HttpTransport and HttpsTransport objects are
* created, so listeners are added to the server the first time they are
* needed.
* @return A SocketListener if a new one was created, or null
*/
protected SocketConnector configureHttps(Zone zone) throws ADKTransportException {
int port = getPort();
if (port == -1) {
throw new ADKTransportException(
"The agent is not configured with a default HTTPS port",
zone);
}
String optHost = getHost();
// If there is no SunJsseListener on this port, create one
Connector listener = null;
Connector[] listeners = sServer.getConnectors();
for (int i = 0; i < listeners.length; i++) {
if (listeners[i] instanceof SocketConnector
&& listeners[i].getPort() == port) {
if (optHost != null && listeners[i].getHost().equalsIgnoreCase(optHost))
listener = listeners[i];
}
}
if (listener == null) {
try {
String ks = getKeyStore();
String ksPwd = getKeyStorePassword();
if ((ADK.debug & ADK.DBG_TRANSPORT) != 0 && log.isInfoEnabled()) {
if (optHost == null) {
log
.info("Creating HTTPS listener for push mode on port "
+ port);
} else {
log.info("Creating HTTPS listener for push mode on "
+ optHost + ":" + port);
}
if (ks == null) {
log.info("Using default Java keystore");
} else {
log.info("Using keystore: " + ks);
}
if (ksPwd.equals("changeit"))
log
.info("Using default Java keystore password 'changeit'");
if (fProps instanceof HttpsProperties)
log
.info("Requiring client authentication: "
+ (((HttpsProperties) fProps)
.getRequireClientAuth() ? "yes"
: "no"));
}
final SslSocketConnector https = new SslSocketConnector();
configureSocketListener(https, port, optHost);
final SslContextFactory httpsContext = https.getSslContextFactory();
if (ks != null)
httpsContext.setKeyStore(ks);
httpsContext.setKeyManagerPassword(ksPwd);
String pwd = getPassword();
if (pwd == null) {
httpsContext.setKeyStorePassword(ksPwd);
} else {
httpsContext.setKeyStorePassword(pwd);
}
HttpsProperties httpsProps = (HttpsProperties) fProps;
String ts = httpsProps.getTrustStore();
String tsPwd = httpsProps.getTrustStorePassword();
if (tsPwd == null)
tsPwd = "changeit";
if (ts != null) {
File tsFile = new File(ts);
if (!tsFile.exists())
throw new ADKTransportException(
"Truststore file not found: "
+ tsFile.getAbsolutePath(), zone);
log.info("(HttpTransport) Using truststore: "
+ tsFile.getAbsolutePath());
System.setProperty("javax.net.ssl.trustStore", ts);
System.setProperty("javax.net.ssl.trustStorePassword",
tsPwd);
} else {
log.info("Using default Java truststore");
}
// The following property tells the SunJsseListener to
// use a seperate truststore from the keystore. Note that if
// the truststore file is set above, it will be used, rather
// than the 'default' java truststore
//https.setUseDefaultTrustStore(true);
if (fProps instanceof HttpsProperties) {
httpsContext.setNeedClientAuth(((HttpsProperties) fProps)
.getRequireClientAuth());
}
return https;
} catch (Exception ioe) {
throw new ADKTransportException(
"Error configuring HTTPS transport: " + ioe, zone);
}
} else {
if ((ADK.debug & ADK.DBG_TRANSPORT) != 0 && log.isDebugEnabled()) {
if (optHost != null) {
log.debug("Already a HTTPS listener on " + optHost + ":"
+ port);
} else {
log.debug("Already a HTTPS listener on port " + port);
}
}
}
return null;
}
/**
* Configures common settings for the Http Listener
*
* @param listener
* @param port
* @param hostName
*/
private void configureSocketListener(SocketConnector listener, int port,
String hostName) {
listener.setName("ADK HTTP Listener");
listener.setPort(port);
if (hostName != null) {
try {
listener.setHost(hostName);
} catch (Exception uhe) {
log.warn("Could not change the local socket address to '"
+ hostName + "': " + uhe, uhe);
}
}
QueuedThreadPool threadPool = new QueuedThreadPool(8);
HttpProperties httpProps = (HttpProperties) fProps;
int maxRequestThreads = httpProps.getMaxConnections();
if (maxRequestThreads > 0) {
threadPool.setMaxThreads(maxRequestThreads);
int minRequestThreads = httpProps.getMinConnections();
if (minRequestThreads <= 0) {
minRequestThreads = (int) Math.ceil(maxRequestThreads / 5);
}
if(minRequestThreads <= 0 ) {
minRequestThreads = 1;
}
threadPool.setMinThreads(minRequestThreads);
int maxIdleTimeMs = httpProps.getMaxIdleTimeMs();
if (maxIdleTimeMs > 0) {
threadPool.setMaxIdleTimeMs(maxIdleTimeMs);
}
int lowResourcesPersistTimeMs = httpProps
.getLowResourcesPersistTimeMs();
if (lowResourcesPersistTimeMs > 0) {
listener.setLowResourcesMaxIdleTime(lowResourcesPersistTimeMs);
}
listener.setThreadPool(threadPool);
if ((ADK.debug & ADK.DBG_TRANSPORT) != 0 && log.isDebugEnabled()) {
log.debug("Set HttpListener.maxThreads to "
+ String.valueOf(maxRequestThreads));
if (minRequestThreads > 0) {
log.debug("Set HttpListener.minThreads to "
+ String.valueOf(minRequestThreads));
}
if (maxIdleTimeMs > 0) {
log.debug("Set HttpListener.maxIdleTimeMs to "
+ String.valueOf(maxIdleTimeMs));
}
if (lowResourcesPersistTimeMs > 0) {
log.debug("Set HttpListener.lowResourcesPersistTimeMs to "
+ String.valueOf(lowResourcesPersistTimeMs));
}
}
}
}
/**
* Create the IProtocolHandler for this transport
* <p>
*
* @return An instance of HttpProtocolHandler
*/
@Override
public IProtocolHandler createProtocolHandler(AgentMessagingMode mode)
throws ADKTransportException {
if (mode == AgentMessagingMode.PULL) {
return new HttpPullProtocolHandler(this);
} else {
if (sServer == null) {
throw new ADKTransportException(
"HttpTransport is not Activated", null);
}
return new HttpPushProtocolHandler(this,sServer);
}
}
/**
* Gets the name of this transport protocol
*
* @return The unique name of the transport protocol, used to identify this
* transport among all transports that may be active in the agent
* @see #getProtocol
*/
public String getName() {
return fProps.getProtocol();
}
/**
* Gets the protocol name
*
* @return The protocol name used in constructing URLs (e.g. "http",
* "https", etc.)
*/
public String getProtocol() {
return fProps.getProtocol();
}
/**
* Determines if this transport is secure or not
*/
public boolean isSecure() {
return getProtocol().equalsIgnoreCase( "https");
}
/**
* Gets the internal Jetty HTTP/HTTPS server. The server is used by all
* instances of the HttpTransport for both HTTP and HTTPS communications
* with the ZIS.
*
* @return The Jetty HttpServer object
*/
public Server getServer() {
return sServer;
}
/**
* Sets the local port this transport protocol will use when listening for
* incoming traffic from the ZIS. The port is assigned to the
* TransportProperties object passed to the constructor.
*
* @param port
* The port number
*/
public void setPort(int port) {
((HttpProperties) fProps).setPort(port);
}
/**
* Gets the local port this transport protocol will use when listening for
* incoming traffic from the ZIS.
*
* @return The port number returned by the TransportProperties object passed
* to the constructor
*/
public int getPort() {
return ((HttpProperties) fProps).getPort();
}
/**
* Sets the local hostname this transport protocol will use when listening
* for incoming traffic from the ZIS. By default, localhost is assumed. The
* hostname is assigned to the TransportProperties object passed to the
* constructor.
*
* @param host
* The host name used for this protocol
*/
public void setHost(String host) {
((HttpProperties) fProps).setHost(host);
}
/**
* Gets the local hostname this transport protocol will use when listening
* for incoming traffic from the ZIS. By default, localhost is assumed.
*
* @return The hostname returned by the TransportProperties object passed to
* the constructor
* @throws ADKTransportException
*/
public String getHost() throws ADKTransportException {
return ((HttpProperties) fProps).getHost();
}
/**
* Gets the keystore file this transport protocol will use for HTTPS.
* <p>
*
* This method has no effect if HttpsProperties were not passed to the
* constructor.
* <p>
*
* @return The keystore file returned by the HttpProperties passed to the
* constructor
*/
public String getKeyStore() {
if (fProps.getProtocol().equalsIgnoreCase("https"))
return ((HttpsProperties) fProps).getKeyStore();
return null;
}
/**
* Sets the keystore file this transport protocol will use for HTTPS.
*
* This method has no effect if HttpsProperties were not passed to the
* constructor.
* <p>
*
* @param keyStore
* The path to a keystore file. The keystore value is assigned to
* the HttpsProperties passed to the constructor.
*/
public void setKeyStore(String keyStore) {
if (fProps.getProtocol().equalsIgnoreCase("https"))
((HttpsProperties) fProps).setKeyStore(keyStore);
}
/**
* Gets the keystore password this transport protocol will use when setting
* up HTTPS.
* <p>
*
* This method has no effect if HttpsProperties were not passed to the
* constructor.
* <p>
*
* @return The keystore password returned by the HttpsProperties passed to
* the constructor
*/
public String getKeyStorePassword() {
if (fProps.getProtocol().equalsIgnoreCase("https"))
return ((HttpsProperties) fProps).getKeyStorePassword();
return null;
}
/**
* Sets the keystore password this transport protocol will use when setting
* up HTTPS. This value does not apply to HTTP connections. The keystore
* password value is assigned to the HttpProperties passed to the
* constructor.
*
* @param keyStorePass
* the keystore password
*/
public void setKeyStorePassword(String keyStorePass) {
if (fProps.getProtocol().equalsIgnoreCase("https"))
((HttpsProperties) fProps).setKeyStorePassword(keyStorePass);
}
/**
* Gets the key password this transport protocol will use when setting up
* HTTPS. When a null value is returned, the caller should use the same
* password as the keystore password. This value does not apply to HTTP
* connections.
*
* @return The key password returned by the HttpProperties passed to the
* constructor
*/
public String getPassword() {
if (fProps.getProtocol().equalsIgnoreCase("https"))
return ((HttpsProperties) fProps).getPassword();
return null;
}
/**
* Sets the key password this transport protocol will use when setting up
* HTTPS. It is typically the same as the keystore password. This value does
* not apply to HTTP connections. The key password is assigned to the
* HttpProperties passed to the constructor.
*
* @param pass
* the key password
*/
public void setPassword(String pass) {
if (fProps.getProtocol().equalsIgnoreCase("https"))
((HttpsProperties) fProps).setPassword(pass);
}
/**
* Enable or disable Client Authentication
*
* @param required
* True if client authentication is required
*/
public void setRequireClientAuth(boolean required) {
if (fProps.getProtocol().equalsIgnoreCase("https"))
((HttpsProperties) fProps).setRequireClientAuth(required);
}
/**
* Determines if Client Authentication is required
*
* @return true if Client Authentication if required
*/
public boolean getRequireClientAuth() {
if (fProps.getProtocol().equalsIgnoreCase("https"))
return ((HttpsProperties) fProps).getRequireClientAuth();
return false;
}
/**
* Modifies the SIF_Protocol element to add Http specific properties
* @param proto
* @param zone
* @throws ADKTransportException
*/
public void configureSIF_Protocol( SIF_Protocol proto, Zone zone, SIFVersion versionOfMessage)
throws ADKTransportException
{
proto.setType( getProtocol().toUpperCase() );
proto.setSecure( isSecure() ? YesNo.YES : YesNo.NO);
String host = ((HttpProperties) fProps).getPushHost();
if (host == null || host.trim().length() == 0)
host = getHost();
int port = ((HttpProperties) fProps).getPushPort();
if (port == -1)
port = getPort();
if (SIFVersion.SIF21.compareTo(versionOfMessage) <= 0) {
SIF_Property acceptEncoding = null;
for (SIF_Property sifProperty : proto.getSIF_Propertys()) {
if ("Accept-Encoding".equals(sifProperty.getSIF_Name())) {
acceptEncoding = sifProperty;
break;
}
}
if (acceptEncoding == null) {
acceptEncoding = new SIF_Property("Accept-Encoding", "gzip;q=1.0, deflate;q=0.7, compress;q=0.6, identity;q=0.5, *;q=0");
proto.addSIF_Property(acceptEncoding);
}
}
proto.setSIF_URL(getProtocol() + "://" + host + ":" + port
+ "/zone/" + zone.getZoneId() + "/");
}
}